package com.tools.web;

import com.tools.common.object.Note;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import eu.bitwalker.useragentutils.Version;
import javax.servlet.http.HttpServletRequest;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 根据 userAgent 请求头
 * 获取客户端的设备信息
 * 包括操作系统、浏览器的
 * 一些元信息
 * */
@Note("根据 userAgent 请求头获取客户端的设备信息" +
        "包括操作系统、浏览器的一些元信息")
public class UserAgentBean {

    @Note("验证 userAgent 字符串的正则")
    public static final Pattern USER_AGENT1 = Pattern.compile("^Mozilla/\\d\\.\\d\\s+\\(+.+?\\)");

    @Note("为了保险再用这个验证一次")
    public static final Pattern USER_AGENT2 = Pattern.compile("\\(+.+?\\)");

    @Note("操作系统")
    private String system;

    @Note("操作系统的名称")
    private String systemName;

    @Note("设备的名称")
    private String deviceName;

    @Note("设备的品牌")
    private String deviceBrand;

    @Note("设备的类型")
    private String deviceType;

    @Note("浏览器名称")
    private String browserName;

    @Note("浏览器版本")
    private String browserVersion;

    @Note("浏览器渲染引擎")
    private String browserRenderEngine;

    public UserAgentBean(String userAgent) {
        if(userAgent == null || userAgent.isEmpty()) throw new IllegalArgumentException("userAgent 字符串为空，无法构建对象");
        String deviceString = this.private_simpleHandle(userAgent);
        this.private_splitSetProperty(deviceString);
        this.private_finalSetProperty(userAgent);
    }

    public UserAgentBean(HttpServletRequest request) {
        this(request.getHeader("User-Agent"));
    }

    public UserAgentBean() {
        this(WebKit.getHttpServletRequest());
    }


    /* ********************************************************************************************
     *
     *          Getter
     *
     * *********************************************************************************************
     * */


    public String getSystem() {
        return system;
    }

    public String getDeviceName() {
        return deviceName;
    }

    public String getDeviceBrand() {
        return deviceBrand;
    }

    public String getDeviceType() {
        return deviceType;
    }

    public String getSystemName() {
        return systemName;
    }

    public String getBrowserName() {
        return browserName;
    }

    public String getBrowserVersion() {
        return browserVersion;
    }

    public String getBrowserRenderEngine() {
        return browserRenderEngine;
    }

    @Override
    public String toString() {
        return "UserAgentBean{" +
                "system='" + system + '\'' +
                ", deviceName='" + deviceName + '\'' +
                ", deviceBrand='" + deviceBrand + '\'' +
                ", deviceType='" + deviceType + '\'' +
                ", systemName='" + systemName + '\'' +
                ", browserName='" + browserName + '\'' +
                ", browserVersion='" + browserVersion + '\'' +
                ", browserRenderEngine='" + browserRenderEngine + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserAgentBean that = (UserAgentBean) o;
        return Objects.equals(system, that.system) && Objects.equals(deviceName, that.deviceName) && Objects.equals(deviceBrand, that.deviceBrand) && Objects.equals(deviceType, that.deviceType) && Objects.equals(systemName, that.systemName) && Objects.equals(browserName, that.browserName) && Objects.equals(browserVersion, that.browserVersion) && Objects.equals(browserRenderEngine, that.browserRenderEngine);
    }

    @Override
    public int hashCode() {
        return Objects.hash(system, deviceName, deviceBrand, deviceType, systemName, browserName, browserVersion, browserRenderEngine);
    }


    /* ********************************************************************************************
     *
     *          私有逻辑
     *
     * *********************************************************************************************
     * */

    @Note("使用两个正则匹配，检查字符串是否符合 User-Agent 请求头的规范，符合则做一些格式化处理后返回")
    private String private_simpleHandle(String userAgent) {
        Matcher m = USER_AGENT1.matcher(userAgent);
        String result = "";
        if (m.find()) {
            result = m.group(0);
        }
        Matcher m2 = USER_AGENT2.matcher(result);
        if (m2.find()) {
            result = m2.group(0);
        }
        return result.replace("(", "")
                .replace(")", "")
                .replace(" U;", "")
                .replace(" zh-cn;", "");
    }

    @Note("将经过处理后 User-Agent 字符串进行切割，截取不同的信息片段赋值给不同的属性")
    private void private_splitSetProperty(String deviceString) {
        String[] array = deviceString.split(";");
        if(array.length >= 1) {
            this.system = array[0].trim();
        }
        if(array.length >= 2) {
            this.deviceName = array[1].trim();
        }
        if(array.length >= 3) {
            this.deviceBrand = array[2].trim();
        }
    }

    @Note("经过上述处理后这里是最后一步初始化值的部分")
    private void private_finalSetProperty(String userAgent) {
        UserAgent ua = UserAgent.parseUserAgentString(userAgent);
        OperatingSystem os = ua.getOperatingSystem();
        this.deviceType = os.getDeviceType().getName();
        this.systemName = os.getName();
        Browser browser = ua.getBrowser();
        this.browserName = browser.getName();
        Version version = browser.getVersion(userAgent);
        this.browserVersion = (version == null) ? null : version.toString();
        this.browserRenderEngine = browser.getRenderingEngine().getName();
    }
}
